package com.atguigu.gmall.activity.service.impl;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.common.execption.GmallException;
import com.atguigu.gmall.model.activity.SeckillGoods;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;

/***
 * 秒杀商品的service层接口的是实现类
 */
@Service
@Slf4j
@Transactional
public class SeckillGoodsServiceImpl implements SeckillGoodsService {

    @Resource
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 获取指定使时间段的商品数据
     *
     * @param dateTime
     * @return
     */
    @Override
    public List<SeckillGoods> getSeckillGoodsList(String dateTime) {
        //从redis中获取，并返回
        return redisTemplate.opsForHash().values(dateTime);
    }

    /**
     * 从redis中获取单个商品
     *
     * @param dateTime
     * @param seckillGoodsId
     * @return
     */
    @Override
    public SeckillGoods getSeckillGoods(String dateTime, String seckillGoodsId) {
        //从redis中获取，并返回
        SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.opsForHash().get(dateTime, seckillGoodsId);

        //返回结果
        return seckillGoods;
    }

    /**
     * 将redis中的商品库存同步到MySQL
     *
     * @param time
     */
    @Override
    public void seckillGoodsStockFromRedisToDb(String time) {
//        System.out.println("同步的商品时间段为："+time);

        //获取指定时间段的所有商品id
        Set seckillGoodsIds = redisTemplate.opsForHash().keys("seckill_goods_stock_count_" + time);

        //遍历商品id，同步数据
        seckillGoodsIds.stream().forEach(seckillGoodsId -> {
            //1 获取redis中的每个商品库存自增值（剩余库存）
            Integer stockCount = (Integer) redisTemplate.opsForHash().get("seckill_goods_stock_count_" + time, seckillGoodsId);

            try{
                //2 更新数据库中的秒杀商品表的库存值
                int update = seckillGoodsMapper.updateStock(seckillGoodsId, stockCount.longValue());
                if (update < 0) {
                    //修改失败
                    throw new GmallException("同步剩余库存失败！！！",null);
                }
            }catch (Exception e){
                //同步失败--记录日志/redis/数据库，实际工作中用t+1天后使用定时任务进行同步，如15-20次都失败，转人工处理
                log.error("商品库存同步失败，商品的时间段为" + time + "，商品id为：" + seckillGoodsId + "，同步的库存为：" + stockCount);
            }finally {
                //3 更新完成后，删除每个商品id对应的库存自增值（hash数据类型中，hk全部删除，大key也就删除了）
                //不管出不出异常
                redisTemplate.opsForHash().delete("seckill_goods_stock_count_" + time, seckillGoodsId);
            }
        });

        //删除限制时间段商品key的过期时间的hk进行清除
        redisTemplate.opsForHash().delete("seckill_goods_times_expire",time);
        //为保证极限请款，在此兜底删除时间段商品key
        redisTemplate.delete(time);
    }
}
